Data cleaning
There are a bunch of small inconsistencies that come with manual data entry that need to be corrected prior to analysis.
Checklist:
Convert dataset to wide (matrix format) done
Standardize species names done
Clean up year column done
Assign NA cover values to 0 done
Standardize treatment labels done
Add “class” statistics to attribute table done
# Gathers dataset to long format before cleaning up, creates species column
long.comp <- gather(waps.comp, key = "species", value = "cover", -c(1:7))
# Removes year labels from species column
spec <- gsub("X\\d\\d\\.*", "", long.comp$species)
# Grabs the first two digits from the species column to make a "year" column
yr <- gsub('\\.', "", long.comp$species)
yr <- gsub("X", "20", yr)
yr <- gsub("[[:alpha:]]+0?", "", yr)
# Reassigns species variable
long.comp$species <- spec
# Attaches year variable
long.comp <- cbind(long.comp, year = as.numeric(yr))
# Lowercase names for dataset
names(long.comp) <- c("plot", "block", "subblock",
"water", "spcomp", "fertilization",
"clipping", "species", "cover", "year")
# Assigns all NA cover values to zero
long.comp$cover[is.na(long.comp$cover)] <- 0
# Reassigns species names to standardized names in the waps.specs dataset
for(i in waps.specs$Species){
long.comp$species <- gsub(paste(i, "$", sep = ""), waps.specs$Newval[waps.specs$Species == i], long.comp$species)
}
After cleaning, we now have two separate dataframes, one that corresponds to different plot treatments/labels and another that corresponds to species abundances:
head(comp.attr)[,1:10]
head(comp.wide)[,1:10]
aegilops ag.big ag.small amsinckia avena big.leaf.dandelion bindweed bro.carinatus bro.hordeaceous bro.madritensis
[1,] 0 0 0 0 12.5 0 0 0 2.5 0
[2,] 0 0 0 0 12.5 0 0 0 2.5 0
[3,] 0 0 0 0 25.0 0 0 0 0.0 0
[4,] 0 0 0 0 75.0 0 0 0 0.0 0
[5,] 0 0 0 0 35.0 0 0 0 0.0 0
[6,] 0 0 0 0 25.0 0 0 0 0.0 0
The species matrix contains a total of 50 unique species. The full list is provided below:
colnames(comp.wide)
[1] "aegilops" "ag.big" "ag.small" "amsinckia" "avena"
[6] "big.leaf.dandelion" "bindweed" "bro.carinatus" "bro.hordeaceous" "bro.madritensis"
[11] "bro.diandrus" "bunchgrass" "cap.bur" "centaurea" "con.arv"
[16] "conyza" "elymus" "epilobium.brach" "erodium.moschatum" "galium"
[21] "geranium" "gumplant" "helianthus" "hordeum.sp" "italian.thistle"
[26] "kickxia.elatine" "lactuca.serriola" "leymus" "lolium" "lotus"
[31] "lupinus" "melilotus" "milk.thistle" "mustard" "nassella"
[36] "oats" "orchard.grass" "phalaris.sp" "poa" "redmaid"
[41] "senecio" "taeniatherum" "tarweed" "thistle" "tragopogon.porrifolius"
[46] "trifolium" "unk.thistle" "veronica" "vicia" "vulpia"
sum(is.na(long.comp$year))
[1] 0
Ordination analysis
unique(ord.att$clip)
[1] "none"
onegroup_trts = c("annuals", "WAPS", "Natives")
multigroup_trts = c("natives+WAPS+annuals", "annuals+natives", "WAPS+annuals", "WAPS+natives", "Centaureasolstitialis+WAPS+annuals")
onespec_trts = unique(comp.attr$sp.trt)[!unique(comp.attr$sp.trt) %in% c(onegroup_trts, multigroup_trts)]
selected.trts <- c(onegroup_trts, multigroup_trts)
selected.clips <- c("none")
selected.fert <- c("none")
selected.water <- c("control-2nd")
ord.mat <- comp.wide[comp.attr$water == selected.water &
comp.attr$sp.trt %in% selected.trts &
comp.attr$clip %in% selected.clips&
comp.attr$fert %in% selected.fert,]
ord.att <- comp.attr[comp.attr$water == selected.water &
comp.attr$sp.trt %in% selected.trts &
comp.attr$clip %in% selected.clips &
comp.attr$fert %in% selected.fert,]
expect_true(nrow(ord.att) == nrow(ord.mat))
# A number of rows have no recorded live plants (not s)
ord.att <- ord.att[rowSums(ord.mat) != 0, ]
ord.mat <- ord.mat[rowSums(ord.mat) != 0, ]
ord.mat <- sqrt(ord.mat)
distmat <- vegdist(ord.mat)
WAPS.mds <- metaMDS(distmat, try = 5, trymax = 50, trace = F)
MDS_xy <- cbind(data.frame(ord.att), data.frame(X = WAPS.mds$points[,1], Y = WAPS.mds$points[,2]))
#WAPS.pca <- prcomp(ord.mat)
#PCA_xy <- cbind(data.frame(ord.att), data.frame(X = WAPS.pca$x[,1], Y = WAPS.pca$x[,2]))
library(ggplot2)
ggplot(MDS_xy, aes(X, Y, color = sp.trt, shape = clip)) + geom_point() + theme_bw() + facet_wrap(~year)


group_abund <- MDS_xy %>% gather(key = "group", value = "cover", annuals, bare, waps, natives, weeds) %>%
replace_na(list(cover = 0))
ggplot(data = group_abund,
aes(x = year,
y = cover,
color = group)) +
geom_point() +
facet_wrap(~sp.trt) +
stat_smooth(method = "lm")

calcRateChange_bray <- function(comdf, comvar, abundvar, timevar){
# Take dataframe,
# Cast by species variable and abundance
# Take just numeric values
# Assign to commat
ssdf <- comdf[,colnames(comdf) %in% c(comvar, abundvar, timevar)]
commat <- spread(data.frame(ssdf),
comvar,
abundvar,
drop = TRUE,
fill = 0)
# Calculate vegetation distance
vd <- vegdist(commat[,-1], method = "euclidean")
td <- dist(commat[,colnames(commat) == timevar])
output <- cbind(interval = c(td), distance = c(vd))
return(data.frame(output))
}
comp_ratechange <- left_join(long.comp, trtlabels)
Joining, by = c("plot", "block")
comp_ratechange <- comp_ratechange %>% filter(species %in% waps.specs$Newval[waps.specs$Type != "class"] &
water == "control-2nd" &
sp.trt %in% selected.trts &
clip %in% selected.clips &
fert %in% selected.fert)
temp_ratechange_bray <- data.frame(comp_ratechange) %>% group_by(block, plot, sp.trt, water) %>%
filter(sp.trt %in% onegroup_trts) %>%
filter(cover > 0) %>%
mutate(cover = cover) %>%
do(calcRateChange_bray(., timevar = "year",
comvar = "species",
abundvar = "cover"))
ggplot(aes(x = interval,
y = distance,
color = sp.trt),
data = temp_ratechange_bray) +
geom_point(alpha = .1) +
facet_wrap(~sp.trt, scales = "fixed") +
stat_smooth(method = "lm", se = FALSE)





LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgZGZfcHJpbnQ6IHBhZ2VkDQotLS0NCg0KYGBge3IsIGVjaG8gPSBGQUxTRX0NCiMgQ2xlYW5pbmcgdXAgV0FQUyBkYXRhDQpsaWJyYXJ5KGRwbHlyKTtsaWJyYXJ5KHRpZHlyKTtsaWJyYXJ5KHZlZ2FuKTtsaWJyYXJ5KHRlc3R0aGF0KQ0KDQpzZXR3ZCgiQzovVXNlcnMvZWJhdHplci9Cb3ggU3luYy9FdmluZXIgbGFiIHNoYXJlZC9FdmFuL1Jlc2VhcmNoIFByb2plY3RzL1dBUFMgRGF0YSIpDQoNCndhcHMuY29tcCA8LSByZWFkLmNzdigiQzovVXNlcnMvZWJhdHplci9Cb3ggU3luYy9FdmluZXIgbGFiIHNoYXJlZC9FdmFuL1Jlc2VhcmNoIFByb2plY3RzL1dBUFMgRGF0YS9XQVBTdGhyb3VnaDIwMTcuY3N2IiwNCiAgICAgICAgICBoZWFkZXIgPSBUUlVFLA0KICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkNCg0KdHJ0bGFiZWxzIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9lYmF0emVyL0JveCBTeW5jL0V2aW5lciBsYWIgc2hhcmVkL0V2YW4vUmVzZWFyY2ggUHJvamVjdHMvV0FQUyBEYXRhL3RydGxhYmVscy5jc3YiLA0KICAgICAgICAgIGhlYWRlciA9IFRSVUUsDQogICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KDQp3YXBzLnNwZWNzIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy9lYmF0emVyL0JveCBTeW5jL0V2aW5lciBsYWIgc2hhcmVkL0V2YW4vUmVzZWFyY2ggUHJvamVjdHMvV0FQUyBEYXRhL1dBUFNzcGVjaWVzLmNzdiIsIA0KICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdzQXNGYWN0b3JzID0gRikNCmBgYA0KDQojIyMgRGF0YSBjbGVhbmluZw0KDQpUaGVyZSBhcmUgYSBidW5jaCBvZiBzbWFsbCBpbmNvbnNpc3RlbmNpZXMgdGhhdCBjb21lIHdpdGggbWFudWFsIGRhdGEgZW50cnkgdGhhdCBuZWVkIHRvIGJlIGNvcnJlY3RlZCBwcmlvciB0byBhbmFseXNpcy4NCg0KX19DaGVja2xpc3Q6X18gIA0KDQoqIENvbnZlcnQgZGF0YXNldCB0byB3aWRlIChtYXRyaXggZm9ybWF0KSBfX2RvbmVfXw0KDQoqIFN0YW5kYXJkaXplIHNwZWNpZXMgbmFtZXMgX19kb25lX18NCg0KKiBDbGVhbiB1cCB5ZWFyIGNvbHVtbiBfX2RvbmVfXw0KDQoqIEFzc2lnbiBOQSBjb3ZlciB2YWx1ZXMgdG8gMCBfX2RvbmVfXw0KDQoqIFN0YW5kYXJkaXplIHRyZWF0bWVudCBsYWJlbHMgX19kb25lX18NCg0KKiBBZGQgImNsYXNzIiBzdGF0aXN0aWNzIHRvIGF0dHJpYnV0ZSB0YWJsZSBfX2RvbmVfXw0KDQpgYGB7ciwgd2FybmluZz1GQUxTRX0NCiMgR2F0aGVycyBkYXRhc2V0IHRvIGxvbmcgZm9ybWF0IGJlZm9yZSBjbGVhbmluZyB1cCwgY3JlYXRlcyBzcGVjaWVzIGNvbHVtbg0KbG9uZy5jb21wIDwtIGdhdGhlcih3YXBzLmNvbXAsIGtleSA9ICJzcGVjaWVzIiwgdmFsdWUgPSAiY292ZXIiLCAtYygxOjcpKQ0KDQojIFJlbW92ZXMgeWVhciBsYWJlbHMgZnJvbSBzcGVjaWVzIGNvbHVtbg0Kc3BlYyA8LSBnc3ViKCJYXFxkXFxkXFwuKiIsICIiLCBsb25nLmNvbXAkc3BlY2llcykNCg0KIyBHcmFicyB0aGUgZmlyc3QgdHdvIGRpZ2l0cyBmcm9tIHRoZSBzcGVjaWVzIGNvbHVtbiB0byBtYWtlIGEgInllYXIiIGNvbHVtbg0KeXIgPC0gZ3N1YignXFwuJywgIiIsIGxvbmcuY29tcCRzcGVjaWVzKQ0KeXIgPC0gZ3N1YigiWCIsICIyMCIsIHlyKQ0KeXIgPC0gZ3N1YigiW1s6YWxwaGE6XV0rMD8iLCAiIiwgeXIpDQoNCiMgUmVhc3NpZ25zIHNwZWNpZXMgdmFyaWFibGUNCmxvbmcuY29tcCRzcGVjaWVzIDwtIHNwZWMNCg0KIyBBdHRhY2hlcyB5ZWFyIHZhcmlhYmxlDQpsb25nLmNvbXAgPC0gY2JpbmQobG9uZy5jb21wLCB5ZWFyID0gYXMubnVtZXJpYyh5cikpDQoNCiMgTG93ZXJjYXNlIG5hbWVzIGZvciBkYXRhc2V0DQpuYW1lcyhsb25nLmNvbXApIDwtIGMoInBsb3QiLCAiYmxvY2siLCAic3ViYmxvY2siLA0KICAgICAgICAgICAgICAgICAgICAgICJ3YXRlciIsICJzcGNvbXAiLCAiZmVydGlsaXphdGlvbiIsDQogICAgICAgICAgICAgICAgICAgICAgImNsaXBwaW5nIiwgInNwZWNpZXMiLCAiY292ZXIiLCAieWVhciIpDQoNCiMgQXNzaWducyBhbGwgTkEgY292ZXIgdmFsdWVzIHRvIHplcm8NCmxvbmcuY29tcCRjb3Zlcltpcy5uYShsb25nLmNvbXAkY292ZXIpXSA8LSAwDQpgYGANCg0KYGBge3J9DQojIFJlYXNzaWducyBzcGVjaWVzIG5hbWVzIHRvIHN0YW5kYXJkaXplZCBuYW1lcyBpbiB0aGUgd2Fwcy5zcGVjcyBkYXRhc2V0DQpmb3IoaSBpbiB3YXBzLnNwZWNzJFNwZWNpZXMpew0KICBsb25nLmNvbXAkc3BlY2llcyA8LSBnc3ViKHBhc3RlKGksICIkIiwgc2VwID0gIiIpLCB3YXBzLnNwZWNzJE5ld3ZhbFt3YXBzLnNwZWNzJFNwZWNpZXMgPT0gaV0sIGxvbmcuY29tcCRzcGVjaWVzKQ0KfQ0KDQojIFJlbW92ZXMgc3BhY2VzIGZyb20gc3BlY2llcyBuYW1lcw0KbG9uZy5jb21wJHNwY29tcCA8LSBnc3ViKCJbWzpzcGFjZTpdXVxcK1tbOnNwYWNlOl1dKiIsICIgXFwrIiwgbG9uZy5jb21wJHNwY29tcCkNCg0KIyBSZW1vdmVzIHdoaXRlc3BhY2UgZnJvbSB0cmVhdG1lbnQgbmFtZXMNCmxvbmcuY29tcCRzcGNvbXAgPC0gZ3N1YigiW1s6c3BhY2U6XV0iLCAiIiwgbG9uZy5jb21wJHNwY29tcCkNCmxvbmcuY29tcCR3YXRlciA8LSBnc3ViKCJbWzpzcGFjZTpdXSIsICIiLCBsb25nLmNvbXAkd2F0ZXIpDQoNCiMgQXNzaWducyBhbGwgTkFzIHRvIHplcm8sIG1lcmdlcyBkdXBsaWNhdGVkIHNwZWNpZXMgbmFtZXMNCmxvbmcuY29tcCRjb3ZlciA8LSBhcy5udW1lcmljKGxvbmcuY29tcCRjb3ZlcikNCmxvbmcuY29tcCRjb3Zlcltpcy5uYShsb25nLmNvbXAkY292ZXIpXSA8LSAwDQpsb25nLmNvbXAgPC0gbG9uZy5jb21wICU+JSBncm91cF9ieShwbG90LCBibG9jaywgc3ViYmxvY2ssIHdhdGVyLCBmZXJ0aWxpemF0aW9uLCBzcGVjaWVzLCB5ZWFyKSAlPiUgc3VtbWFyaXNlKGNvdmVyID0gc3VtKGNvdmVyKSkNCg0KIyBTcHJlYWRzIGRhdGFzZXQgdG8gd2lkZSBmb3JtYXQNCmNvbXAud2lkZSA8LSBzcHJlYWQobG9uZy5jb21wLCBrZXkgPSAic3BlY2llcyIsIHZhbHVlID0gImNvdmVyIikNCmNvbXAuYXR0ciA8LSBzZWxlY3QoY29tcC53aWRlLCBvbmVfb2YoYygieWVhciIsIHdhcHMuc3BlY3MkTmV3dmFsW3dhcHMuc3BlY3MkVHlwZSA9PSAiY2xhc3MiXSkpKQ0KY29tcC53aWRlIDwtIHVuZ3JvdXAoY29tcC53aWRlKSAlPiUgIHNlbGVjdChvbmVfb2Yod2Fwcy5zcGVjcyROZXd2YWxbd2Fwcy5zcGVjcyRUeXBlICE9ICJjbGFzcyJdKSkNCmNvbXAud2lkZSA8LSBhcHBseShjb21wLndpZGUsIDIsIGFzLm51bWVyaWMpDQpjb21wLndpZGVbaXMubmEoY29tcC53aWRlKV0gPC0gMA0KDQojIE1lcmdlcyB3aXRoIHRyZWF0bWVudCBsYWJlbHMNCmNvbXAuYXR0ciA8LSBsZWZ0X2pvaW4oY29tcC5hdHRyLCB0cnRsYWJlbHMpDQpjb21wLmF0dHIkc3AudHJ0IDwtIGdzdWIoIltbOnNwYWNlOl1dIiwgIiIsIGNvbXAuYXR0ciRzcC50cnQpDQpgYGANCg0KQWZ0ZXIgY2xlYW5pbmcsIHdlIG5vdyBoYXZlIHR3byBzZXBhcmF0ZSBkYXRhZnJhbWVzLCBvbmUgdGhhdCBjb3JyZXNwb25kcyB0byBkaWZmZXJlbnQgcGxvdCB0cmVhdG1lbnRzL2xhYmVscyBhbmQgYW5vdGhlciB0aGF0IGNvcnJlc3BvbmRzIHRvIHNwZWNpZXMgYWJ1bmRhbmNlczoNCg0KYGBge3J9DQpoZWFkKGNvbXAuYXR0cilbLDE6MTBdDQpoZWFkKGNvbXAud2lkZSlbLDE6MTBdDQpgYGANCg0KVGhlIHNwZWNpZXMgbWF0cml4IGNvbnRhaW5zIGEgdG90YWwgb2YgNTAgdW5pcXVlIHNwZWNpZXMuIFRoZSBmdWxsIGxpc3QgaXMgcHJvdmlkZWQgYmVsb3c6DQpgYGB7cn0NCmNvbG5hbWVzKGNvbXAud2lkZSkNCmBgYA0KDQoNCiMgT3JkaW5hdGlvbiBhbmFseXNpcw0KDQpgYGB7cn0NCm9uZWdyb3VwX3RydHMgPSBjKCJhbm51YWxzIiwgIldBUFMiLCAiTmF0aXZlcyIpDQptdWx0aWdyb3VwX3RydHMgPSBjKCJuYXRpdmVzK1dBUFMrYW5udWFscyIsICJhbm51YWxzK25hdGl2ZXMiLCAiV0FQUythbm51YWxzIiwgIldBUFMrbmF0aXZlcyIsICJDZW50YXVyZWFzb2xzdGl0aWFsaXMrV0FQUythbm51YWxzIikNCm9uZXNwZWNfdHJ0cyA9IHVuaXF1ZShjb21wLmF0dHIkc3AudHJ0KVshdW5pcXVlKGNvbXAuYXR0ciRzcC50cnQpICVpbiUgYyhvbmVncm91cF90cnRzLCBtdWx0aWdyb3VwX3RydHMpXQ0KDQpzZWxlY3RlZC50cnRzIDwtIGMob25lZ3JvdXBfdHJ0cykNCnNlbGVjdGVkLmNsaXBzIDwtIGMoIm5vbmUiKQ0Kc2VsZWN0ZWQuZmVydCA8LSBjKCJub25lIikNCnNlbGVjdGVkLndhdGVyIDwtIGMoImNvbnRyb2wtMm5kIikgDQoNCm9yZC5tYXQgPC0gY29tcC53aWRlW2NvbXAuYXR0ciR3YXRlciA9PSBzZWxlY3RlZC53YXRlciAmDQogICAgICAgICAgICAgICAgICAgICBjb21wLmF0dHIkc3AudHJ0ICVpbiUgc2VsZWN0ZWQudHJ0cyAmDQogICAgICAgICAgICAgICAgICAgICBjb21wLmF0dHIkY2xpcCAlaW4lIHNlbGVjdGVkLmNsaXBzJg0KICAgICAgICAgICAgICAgICAgICAgY29tcC5hdHRyJGZlcnQgJWluJSBzZWxlY3RlZC5mZXJ0LF0NCg0Kb3JkLmF0dCA8LSBjb21wLmF0dHJbY29tcC5hdHRyJHdhdGVyID09IHNlbGVjdGVkLndhdGVyICYNCiAgICAgICAgICAgICAgICAgICAgIGNvbXAuYXR0ciRzcC50cnQgJWluJSBzZWxlY3RlZC50cnRzICYNCiAgICAgICAgICAgICAgICAgICAgIGNvbXAuYXR0ciRjbGlwICVpbiUgc2VsZWN0ZWQuY2xpcHMgJg0KICAgICAgICAgICAgICAgICAgICAgY29tcC5hdHRyJGZlcnQgJWluJSBzZWxlY3RlZC5mZXJ0LF0NCg0KZXhwZWN0X3RydWUobnJvdyhvcmQuYXR0KSA9PSBucm93KG9yZC5tYXQpKQ0KDQojIEEgbnVtYmVyIG9mIHJvd3MgaGF2ZSBubyByZWNvcmRlZCBsaXZlIHBsYW50cyAobm90IHMpDQpvcmQuYXR0IDwtIG9yZC5hdHRbcm93U3VtcyhvcmQubWF0KSAhPSAwLCBdDQpvcmQubWF0IDwtIG9yZC5tYXRbcm93U3VtcyhvcmQubWF0KSAhPSAwLCBdDQpvcmQubWF0IDwtIHNxcnQob3JkLm1hdCkNCg0KZGlzdG1hdCA8LSB2ZWdkaXN0KG9yZC5tYXQpDQpXQVBTLm1kcyA8LSBtZXRhTURTKGRpc3RtYXQsIHRyeSA9IDUsIHRyeW1heCA9IDUwLCB0cmFjZSA9IEYpDQpNRFNfeHkgPC0gY2JpbmQoZGF0YS5mcmFtZShvcmQuYXR0KSwgZGF0YS5mcmFtZShYID0gV0FQUy5tZHMkcG9pbnRzWywxXSwgWSA9IFdBUFMubWRzJHBvaW50c1ssMl0pKQ0KDQojV0FQUy5wY2EgPC0gcHJjb21wKG9yZC5tYXQpDQojUENBX3h5IDwtIGNiaW5kKGRhdGEuZnJhbWUob3JkLmF0dCksIGRhdGEuZnJhbWUoWCA9IFdBUFMucGNhJHhbLDFdLCBZID0gV0FQUy5wY2EkeFssMl0pKQ0KYGBgDQoNCmBgYHtyfQ0KbGlicmFyeShnZ3Bsb3QyKQ0KZ2dwbG90KE1EU194eSwgYWVzKFgsIFksIGNvbG9yID0gc3AudHJ0LCBzaGFwZSA9IGNsaXApKSArIGdlb21fcG9pbnQoKSArIHRoZW1lX2J3KCkgKyBmYWNldF93cmFwKH55ZWFyKQ0KYGBgDQpgYGB7cn0NCmdncGxvdChNRFNfeHlbb3JkZXIoTURTX3h5JHllYXIpLF0sIGFlcyhYLCBZLCBjb2xvciA9IGFzLmZhY3RvcihwbG90KSkpICsgDQogIGdlb21fcG9pbnQoKSArIA0KICBnZW9tX3BhdGgoIGFycm93ID0gYXJyb3codW5pdCgwLjMwLCJjbSIpLCBhbmdsZSA9IDE1LCBlbmRzID0gImxhc3QiLCB0eXBlID0gImNsb3NlZCIpLCBhbHBoYSA9IC41KSArIA0KICB0aGVtZV9idygpICsgDQogIGZhY2V0X2dyaWQoc3AudHJ0IH4gYmxvY2spICsNCiAgZ3VpZGVzKGNvbG9yID0gRkFMU0UpDQoNCmBgYA0KYGBge3J9DQpncm91cF9hYnVuZCA8LSBNRFNfeHkgJT4lIGdhdGhlcihrZXkgPSAiZ3JvdXAiLCB2YWx1ZSA9ICJjb3ZlciIsIGFubnVhbHMsIGJhcmUsIHdhcHMsIG5hdGl2ZXMsIHdlZWRzKSAlPiUNCiAgcmVwbGFjZV9uYShsaXN0KGNvdmVyID0gMCkpIA0KDQpnZ3Bsb3QoZGF0YSA9IGdyb3VwX2FidW5kLCANCiAgICAgICBhZXMoeCA9IHllYXIsDQogICAgICAgICAgIHkgPSBjb3ZlciwNCiAgICAgICAgICAgY29sb3IgPSBncm91cCkpICsNCiAgZ2VvbV9wb2ludCgpICsgDQogIGZhY2V0X3dyYXAofnNwLnRydCkgKw0KICBzdGF0X3Ntb290aChtZXRob2QgPSAibG0iKQ0KDQoNCmBgYA0KDQoNCmBgYHtyfQ0KY2FsY1JhdGVDaGFuZ2VfYnJheSA8LSBmdW5jdGlvbihjb21kZiwgY29tdmFyLCBhYnVuZHZhciwgdGltZXZhcil7DQogICMgVGFrZSBkYXRhZnJhbWUsDQogICMgQ2FzdCBieSBzcGVjaWVzIHZhcmlhYmxlIGFuZCBhYnVuZGFuY2UNCiAgIyBUYWtlIGp1c3QgbnVtZXJpYyB2YWx1ZXMNCiAgIyBBc3NpZ24gdG8gY29tbWF0DQogIHNzZGYgPC0gY29tZGZbLGNvbG5hbWVzKGNvbWRmKSAlaW4lIGMoY29tdmFyLCBhYnVuZHZhciwgdGltZXZhcildDQogIGNvbW1hdCA8LSBzcHJlYWQoZGF0YS5mcmFtZShzc2RmKSwgDQogICAgICAgICAgICAgICAgICAgY29tdmFyLA0KICAgICAgICAgICAgICAgICAgIGFidW5kdmFyLA0KICAgICAgICAgICAgICAgICAgIGRyb3AgPSBUUlVFLA0KICAgICAgICAgICAgICAgICAgIGZpbGwgPSAwKQ0KICANCiAgIyBDYWxjdWxhdGUgdmVnZXRhdGlvbiBkaXN0YW5jZQ0KICB2ZCA8LSB2ZWdkaXN0KGNvbW1hdFssLTFdLCBtZXRob2QgPSAiZXVjbGlkZWFuIikNCiAgdGQgPC0gZGlzdChjb21tYXRbLGNvbG5hbWVzKGNvbW1hdCkgPT0gdGltZXZhcl0pDQogIG91dHB1dCA8LSBjYmluZChpbnRlcnZhbCA9IGModGQpLCBkaXN0YW5jZSA9IGModmQpKQ0KICByZXR1cm4oZGF0YS5mcmFtZShvdXRwdXQpKQ0KfQ0KDQpjb21wX3JhdGVjaGFuZ2UgPC0gbGVmdF9qb2luKGxvbmcuY29tcCwgdHJ0bGFiZWxzKQ0KDQpjb21wX3JhdGVjaGFuZ2UgPC0gY29tcF9yYXRlY2hhbmdlICAlPiUgZmlsdGVyKHNwZWNpZXMgJWluJSB3YXBzLnNwZWNzJE5ld3ZhbFt3YXBzLnNwZWNzJFR5cGUgIT0gImNsYXNzIl0gJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdhdGVyID09ICJjb250cm9sLTJuZCIgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwLnRydCAlaW4lIHNlbGVjdGVkLnRydHMgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsaXAgJWluJSBzZWxlY3RlZC5jbGlwcyAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVydCAlaW4lIHNlbGVjdGVkLmZlcnQpDQoNCg0KdGVtcF9yYXRlY2hhbmdlX2JyYXkgPC0gZGF0YS5mcmFtZShjb21wX3JhdGVjaGFuZ2UpICU+JSBncm91cF9ieShibG9jaywgcGxvdCwgc3AudHJ0LCB3YXRlcikgJT4lDQogIGZpbHRlcihzcC50cnQgJWluJSBvbmVncm91cF90cnRzKSAlPiUNCiAgZmlsdGVyKGNvdmVyID4gMCkgJT4lDQogIG11dGF0ZShjb3ZlciA9IGNvdmVyKSAlPiUNCiAgZG8oY2FsY1JhdGVDaGFuZ2VfYnJheSguLCB0aW1ldmFyID0gInllYXIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgIGNvbXZhciA9ICJzcGVjaWVzIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICBhYnVuZHZhciA9ICJjb3ZlciIpKQ0KDQpnZ3Bsb3QoYWVzKHggPSBpbnRlcnZhbCwNCiAgICAgICAgICAgeSA9IGRpc3RhbmNlLA0KICAgICAgICAgICBjb2xvciA9IHNwLnRydCksDQogICAgICAgZGF0YSA9IHRlbXBfcmF0ZWNoYW5nZV9icmF5KSArDQogIGdlb21fcG9pbnQoYWxwaGEgPSAuMSkgKw0KICBmYWNldF93cmFwKH5zcC50cnQsIHNjYWxlcyA9ICJmaXhlZCIpICsgDQogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRkFMU0UpDQoNCmBgYA0KYGBge3J9DQpzdW1tYXJ5KGxtKGRpc3RhbmNlIH4gaW50ZXJ2YWwgKiBzcC50cnQsIGRhdGEgPSB0ZW1wX3JhdGVjaGFuZ2VfYnJheSkpDQoNCnBsb3QobG0oZGlzdGFuY2UgfiBpbnRlcnZhbCAqIHNwLnRydCwgZGF0YSA9IHRlbXBfcmF0ZWNoYW5nZV9icmF5KSkNCmBgYA0KDQoNCg==